<template>
	<div class="app-data-import-content">
		<a-upload-dragger
			v-model:fileList="fileList"
			name="file"
			:multiple="false"
			class="app-data-import__upload"
			:maxCount="1"
			:before-upload="beforeUpload"
			@remove="handleRemove"
		>
			<p class="ant-upload-drag-icon">
				<img class="icon-link" src="/assets/img/icon-import.svg" />
			</p>
			<p class="ant-upload-text">{{ $t('function.dataimport.selectfile') }}</p>
			<p class="ant-upload-hint" v-if="uploading">
				{{ $t('function.dataimport.nowupload') }}
				{{ uploadedProgress }}%，
				{{ $t('function.dataimport.toolarge') }}
			</p>
		</a-upload-dragger>
		<div class="app-data-import__describe">
			<div>{{ $t('function.dataimport.datatemplatemessage') }}</div>
			<span class="app-data-import__describe__link" @click="handleDownloadTemp">
				<img class="icon-link" src="/assets/img/icon-link.svg" />
				{{ viewParams ? viewParams.appDeLogicName : ''
				}}{{ $t('function.dataimport.datatemplate') }}
			</span>
		</div>
		<a-space align="end" class="app-data-import__footer">
			<a-button type="primary" @click="handleCancel">{{
				$t('function.dataimport.cancel')
			}}</a-button>
			<a-button
				type="primary"
				:loading="uploading"
				:disabled="fileList.length === 0"
				@click="handleUpload"
				>{{ $t('function.dataimport.uploadserver') }}</a-button
			>
		</a-space>
	</div>
</template>

<script setup lang="ts">
import {
	IContext,
	IParam,
	ViewActionType,
	srfpluralize,
	ExportExcelUtil,
	deepCopy,
	ICodeListItem,
} from '@/core';
import { UploadProps } from 'ant-design-vue';
import { PropType } from 'vue';
import axios from 'axios';
import XLSX from 'xlsx';
const props = defineProps({
	context: {
		type: Object as PropType<IContext>,
	},
	viewParams: {
		type: Object as PropType<IParam>,
	},
});
const emit = defineEmits<{
	(
		event: 'view-action',
		name: string,
		action: ViewActionType,
		data: IParam[]
	): void;
}>();
const fileList = ref<any[]>([]);
const uploading = ref<boolean>(false);
const uploadedProgress = ref<number>(0);
const successCount = ref<number>(0);
const errorInfos = ref<IParam[]>([]);

const handleCancel = () => {
	emit('view-action', 'dataImport', 'viewClose', []);
};

/**
 * 下载导入模板
 */
const handleDownloadTemp = () => {
	if (import.meta.env.VITE_MODE === 'R7') {
		handleDownloadTempWithOld();
	} else {
		handleDownloadTempWithNew();
	}
};

/**
 * 下载导入模板（R7标准模式）
 */
const handleDownloadTempWithOld = async () => {
	const importItems: IParam[] =
		props.viewParams && props.viewParams.importItems
			? props.viewParams.importItems
			: [];
	const tHeaders: string[] = importItems.map((item: IParam) => item.caption);
	const excel = await ExportExcelUtil.getInstance().getExcel();
	excel.export_json_to_excel({
		header: tHeaders, //表头 必填
		data: [], //具体数据 必填
		filename: `${
			props.viewParams && props.viewParams.appDeLogicName
		}导入数据模板`,
		autoWidth: true, //非必填
		bookType: 'xlsx', //非必填
	});
};

/**
 * 下载导入模板（Cloud标准模式）
 */
const handleDownloadTempWithNew = () => {
	let requestUrl = '';
	if (props.viewParams) {
		const { srfparentkey, srfparentdename, serviceName, importId } =
			props.viewParams;
		if (srfparentkey && srfparentdename && srfparentdename !== serviceName) {
			requestUrl += `/${srfpluralize(srfparentdename)}/${srfparentkey}`;
		}
		requestUrl += `/${srfpluralize(serviceName)}/importtemplate`;
		if (importId) {
			requestUrl += `?srfimporttag=${importId}`;
		}
	}
	axios({
		url: requestUrl,
		method: 'get',
		responseType: 'blob',
	}).then((response: any) => {
		if (response.status == 200) {
			let fileName = response.headers['content-disposition']
				.split(';')
				.find((str: string) => str.indexOf('filename=') != -1)
				?.slice(9);
			fileName = decodeURIComponent(fileName);
			let blob = new Blob([response.data], {
				type: 'application/vnd.ms-excel',
			});
			let elink = document.createElement('a');
			elink.download = fileName;
			elink.style.display = 'none';
			elink.href = URL.createObjectURL(blob);
			document.body.appendChild(elink);
			elink.click();
			URL.revokeObjectURL(elink.href); // 释放URL 对象
			document.body.removeChild(elink);
		}
	});
};

const handleRemove: UploadProps['onRemove'] = (file) => {
	if (fileList.value) {
		const index = fileList.value.indexOf(file);
		const newFileList = fileList.value.slice();
		newFileList.splice(index, 1);
		fileList.value = newFileList;
	}
};

const beforeUpload: UploadProps['beforeUpload'] = (file) => {
	fileList.value = [...(fileList.value || []), file];
	return false;
};

/**
 * 上传
 */
const handleUpload = () => {
	if (import.meta.env.VITE_MODE === 'R7') {
		handleUploadWithOld();
	} else {
		handleUploadWithNew();
	}
};

/**
 * 上传（R7标准模式）
 */
const handleUploadWithOld = () => {
	if (fileList.value && fileList.value.length > 0) {
		let importData: IParam[] = [];
		const file = fileList.value[0];
		const reader = new FileReader();
		reader.onload = (e: any) => {
			let data = e.target.result;
			const workBookData = XLSX.read(data, { type: 'binary', cellDates: true });
			let xlsxData: IParam[] = XLSX.utils.sheet_to_json(
				workBookData.Sheets[workBookData.SheetNames[0]]
			);
			let list = getFirstRow(workBookData);
			xlsxData = addXlsxData(xlsxData, list);
			importData = deepCopy(xlsxData) as IParam[];
			if (importData.length > 0) {
				transformData(importData).then(() => {
					handleSliceUpload(importData);
				});
			}
		};
		reader.readAsBinaryString(file.originFileObj);
	}
};

const transformData = async (data: IParam[]): Promise<void> => {
	const importItems =
		props.viewParams && props.viewParams.importItems
			? props.viewParams.importItems
			: [];
	const codeListMap: Map<string, ICodeListItem[]> = new Map();
	for (const item of importItems) {
		if (item.codeListTag) {
			const result = await App.getAppCodeListHelper().getCodeListItems(
				item.codeListTag,
				props.context,
				props.viewParams
			);
			if (result.ok) {
				codeListMap.set(item.name, result.data);
			}
		}
	}
	data.forEach((item: IParam) => {
		Object.keys((key: string) => {
			const value = item[key];
			if (value !== null && value !== undefined) {
				//	代码表翻译
				if (codeListMap.has(key)) {
					const _value = (codeListMap.get(key) || []).find(
						(clItem: ICodeListItem) => {
							return clItem.text === value;
						}
					);
					item[key] = _value ? _value : value;
				}
			}
		});
	});
};

const handleSliceUpload = async (data: IParam[]) => {
	uploadedProgress.value = 0;
	errorInfos.value.length = 0;
	if (!props.viewParams) {
		return;
	}
	if (!props.viewParams.serviceName) {
		App.getNotificationHelper().warning('', '未配置实体服务');
		return;
	}
	//	开始上传
	uploading.value = true;
	const dataService = await App.getDataService(
		props.viewParams.serviceName,
		props.context
	);
	const sliceSize = App.getProjectSetting().sliceUploadCnt || 500;
	const { importId, ignoreError } = props.viewParams;
	const sliceUpload = async (cnt: number) => {
		if (cnt >= data.length) {
			//	上传完成
			uploading.value = false;
			return;
		}
		const sliceData = data.slice(cnt, cnt + sliceSize);
		try {
			const response = await dataService.importData(props.context, {
				name: importId,
				ignoreError,
				importData: sliceData,
			});
			const result = response.data;
			successCount.value += result.success;
			if (result.total != result.success) {
				handleErrorInfo(result.errorinfo, cnt);
				if (!ignoreError) {
					uploading.value = false;
					return;
				}
			}
			uploadedProgress.value = Number(((cnt / data.length) * 100).toFixed(2));
			await sliceUpload(cnt + sliceSize);
		} catch (error: any) {
			if (error.errorinfo) {
				handleErrorInfo(error.errorinfo, cnt);
				if (!ignoreError) {
					uploading.value = false;
					return;
				}
			}
			uploadedProgress.value = Number(((cnt / data.length) * 100).toFixed(2));
			await sliceUpload(cnt + sliceSize);
		}
	};
	sliceUpload(0);
};

const handleErrorInfo = (infos: IParam[], cnt: number) => {
	if (infos && infos.length) {
		infos.forEach((item: any) => {
			errorInfos.value.push(
				Object.assign(
					{
						index: cnt + item.row,
					},
					item
				)
			);
		});
	}
};

const getFirstRow = (wb: XLSX.WorkBook) => {
	//// 读取的excel单元格内容
	let wbData = wb.Sheets[wb.SheetNames[0]];
	// 匹配excel第一行的内容
	let re = /^[A-Z]1$/;
	let temparr = [];
	// excel第一行内容赋值给数组
	for (let key in wbData) {
		if (wbData.hasOwnProperty(key)) {
			if (re.test(key)) {
				temparr.push(wbData[key].h);
			}
		}
	}
	return temparr;
};

const addXlsxData = (xlsxData: IParam[], list: number[]) => {
	// 空白字段替换值
	let addData = null;
	for (let i = 0; i < xlsxData.length; i++) {
		// 要被JSON的数组
		for (let j = 0; j < list.length; j++) {
			// excel第一行内容
			if (!xlsxData[i][list[j]]) {
				xlsxData[i][list[j]] = addData;
			}
		}
	}
	return xlsxData;
};

/**
 * 上传（cloud标准模式）
 */
const handleUploadWithNew = () => {
	if (fileList.value) {
		let requestUrl = '';
		if (props.viewParams) {
			const { srfparentkey, srfparentdename, serviceName, importId } =
				props.viewParams;
			if (
				srfparentkey &&
				srfparentdename &&
				srfparentdename.toLowerCase() !== serviceName.toLowerCase()
			) {
				requestUrl += `/${srfpluralize(srfparentdename)}/${srfparentkey}`;
			}
			requestUrl += `/${srfpluralize(
				serviceName.toLowerCase()
			)}/importtemplate`;
			if (importId) {
				requestUrl += `?srfimporttag=${importId}`;
			}
		}
		const data = new FormData();
		data.append('file', fileList.value[0].originFileObj);
		axios
			.post(requestUrl, data, {
				headers: { 'Content-Type': 'multipart/form-data' },
				onUploadProgress: (progressEvent: any) => {
					uploadedProgress.value = Math.floor(
						(progressEvent.loaded / progressEvent.total) * 100
					);
				},
			})
			.then((res: any) => {
				if (res && res.status && res.status == 200) {
					const { data: data } = res;
					fileList.value = [];
					uploading.value = false;
					if (props.viewParams && props.viewParams.ignoreError) {
						if (
							data &&
							Object.prototype.toString.call(data) === '[object Object]' &&
							Object.keys(data).length > 0
						) {
							Object.keys(data).forEach((key: string) => {
								if (data[key]['errorInfo']) {
									App.getNotificationHelper().error(
										App.ts('common.generic.error'),
										`第${Number(key) + 1}行:${data[key]['errorInfo']}`
									);
								}
								if (data[key]['successInfo']) {
									App.getNotificationHelper().success(
										App.ts('common.generic.success'),
										`第${Number(key) + 1}行:${data[key]['successInfo']}`
									);
								}
							});
						}
					} else {
						App.getNotificationHelper().success(
							App.ts('function.dataimport.read'),
							App.ts('function.dataimport.completed')
						);
					}
				}
			})
			.catch((error: any) => {
				uploading.value = false;
				if (error && error.status && error.status !== 200) {
					App.getNotificationHelper().error(
						App.ts('common.generic.error'),
						error.data?.message
					);
				}
			});
	}
};
</script>
